GIS数据处理-cesium中模型位置设置

15 篇文章 14 订阅

GIS数据处理-cesium中模型位置设置

介绍

最近我收到不少人私信询问我,在cesium中加载3dtiles模型后如何调整模型位置,这里我就统一的介绍一下,我是怎么处理的以供大家参考。

常见模型分类:

  1. 倾斜摄影模型:由于模型带地理位置,基本上不需要调整模型位置。
  2. 人工模型:模型是没有坐标信息的,这个时候就需要我们调整模型位置。

还有点云等数据,这里就不介绍了。

我在这里推荐两个方法,一个是使用cesiumlab来操作(可视化操作),另一个是使用代码操作

代码原理

cesium中加载3dtiles模型代码如下:

viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url: 'http://localhost:8080/data/testModel/tileset.json',
        modelMatrix: Cesium.Matrix4.fromArray(
            [0.9972458032561666, 0.04372029028528979, 0.05991113506964879, 0,
              -0.03623787897545647, 0.9920229449104262, -0.12073646051879428, 0,
              -0.06471185374661931, 0.11823287609043515, 0.9908750491338749, 0,
              -663.0794944260269, 1211.490494620055, 2974.1003134818748, 1]),
      }));

new Cesium.Cesium3DTileset(options)

用于流式传输海量异构 3D 地理空间数据集

options选项

名称类型默认描述
url网络资源,字符串瓦片集 JSON 文件的 url
modelMatrix矩阵4(Matrix4)Matrix4.IDENTITY转换瓦片集的根瓦片的 4x4 转换矩阵

这里我们要详细讲述一下矩阵的用处,cesium中所有的坐标最后都会转换成空间笛卡尔坐标也就是我们常说的三维空间坐标系。在笛卡尔坐标系中模型进行坐标系转换,这里就涉及到转换矩阵了。

tileset.modelMatrix,使用这个属性就可以在数据基础上进行坐标转换了

平移思路

  1. 获取当前瓦片数据集的包裹范围(boundingSphere)中心(此时参考系是三维笛卡尔坐标系)
  2. 计算当参考系是局部坐标(局部坐标系的原点为模型包围范围的中心)时,此位置为原点的局部坐标系,到世界坐标的转换矩阵(eastNorthUpToFixedFrame)
  3. 利用上一步的转换矩阵,左乘一个局部平移向量,得到此平移向量在世界坐标系下的平移目标位置(矩阵×向量,结果是向量)
  4. 向量相减:世界坐标系下,指向平移目标点位的目标向量 - 指向数据集中心的向量,得到世界坐标系下的平移向量。
  5. 将世界坐标系下的平移向量转换成平移矩阵,赋予 tileset.modelMatrix
代码实现
tileset
  .readyPromise
  .then(tileset => {
    // Cartesian3 三维笛卡儿坐标系中的瓦片中心点
    const tileset_center = tileset.boundingSphere.center; 
    // Matrix4(四阶矩阵)局部参考系到世界参考系下的转换矩阵
    const frompoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset_center);
    // 向模型中心为原点,正北为y,正东为x,地心朝上为z分别平移 310、-140、10米
    const local_translation = new Cesium.Cartesian3(310, -140, 10); 
    const result = new Cesium.Cartesian3(0,0,0);
    // 转换矩阵左乘局部平移向量,结果存储在 result 中,结果是世界坐标下的平移终点向量
    Cesium.Matrix4.multiplyByPoint(frompoint_to_world_matrix, local_translation, result); 
    const targetpoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(result);
    // 世界坐标系下,指向平移目标点位的目标向量 - 指向数据集中心的向量,得到世界坐标系下的平移向量
    const world_translation = new Cesium.Cartesian3(
      targetpoint_to_world_matrix[12] - frompoint_to_world_matrix[12],
      targetpoint_to_world_matrix[13] - frompoint_to_world_matrix[13],
      targetpoint_to_world_matrix[14] - frompoint_to_world_matrix[14],
    ); 
    // 构造平移矩阵并赋值
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(world_translation); 
    // 相机视角移动到模型位置
    viewer.zoomTo(tileset);
});

cesium中坐标参考系

  • 红点:frompoint(模型包围范围中心点,也是局部坐标系原点)
  • 蓝点:targetpoint(frompoint局部坐标向东向北向上偏移各 310、-140、10米 后得到的目标点)
  • 红向量:世界坐标系下的模型包围范围中心点(局部坐标系原点、起始点)向量
  • 蓝向量:世界坐标系下的目标点向量
  • 绿向量:平移向量。如果是局部坐标,那么就是 (310, -140, 10),如果是世界坐标下的,那就是 蓝向量 - 红向量

cesium 的场景数据最终都是世界坐标的,所以要求的是绿向量的世界坐标表达,然后构造平移矩阵。

现在是已知红向量和局部坐标的绿向量,要先求蓝向量,才能得到世界坐标系下的绿向量。

旋转思路

局部旋转,先将模型移动到世界坐标中心,旋转后,再移动到原来的地方,即

tileset.modelMatrix

preview

其中,

img

是一个平移矩阵,只需使用模型中心向量取个负值即可

img

则是从世界坐标中心再移动到模型原点

注意,这里是左乘优先顺序,从右往左乘。

代码实现
tileset
  .readyPromise
  .then(tileset => {
    const tileset_center = tileset.boundingSphere.center; // Cartesian3 三维笛卡儿坐标系中的瓦片中心点
    // Matrix4(四阶矩阵)局部参考系到世界参考系下的转换矩阵
    const backto_matrix = Cesium.Matrix4.fromTranslation(tileset_center);
    // 模型向量取负值
    const moveto_vec = Cesium.Cartesian3.multiplyByScalar(tileset_center, -1, new Cesium.Cartesian3());
    //移动到世界坐标系原点的矩阵
    const moveto_matrix = Cesium.Matrix4.fromTranslation(moveto_vec);

    /* 绕x(即东方轴)转90度 */
    const cos_rotateX = Math.cos(Math.PI/2);
    const sin_rotateX = Math.sin(Math.PI/2);
    const arr = [1,0,0,0,  0, cos_rotateX, sin_rotateX,0,   0,-sin_rotateX,cos_rotateX,0, 0,0,0,1];
    //旋转矩阵
    const rotateX_matrix = Cesium.Matrix4.fromArray(arr);

    /* 计算最终矩阵 */
    // 获得在世界原点旋转后的矩阵
    const temp = Cesium.Matrix4.multiply(rotateX_matrix, moveto_matrix, new Cesium.Matrix4());
    // 获得旋转后移动回原来位置的矩阵
    const r = Cesium.Matrix4.multiply(backto_matrix, temp, new Cesium.Matrix4());

    tileset.modelMatrix = r; // 构造平移矩阵并赋值
    // 相机视角移动到模型位置
    viewer.zoomTo(tileset);
});

缩放思路

缩放思路和旋转类似,先移动到世界坐标系中心,缩放,然后再移动到原来的地方

tileset.modelMatrix

img

代码实现

待实现

参考大佬原文

工具使用

上面介绍了代码的实现步骤,现在介绍直接使用工具的方式

cesiumlab

不得不再次推荐,国人良心工具cesiumlab,下载安装即可

步骤

生成3dtiles切片的教程我之前已经写了,这里默认大家都准备好了

我这里使用的是人工建模的模型,没有地理坐标信息,方便给大家演示

加载数据

打开cesiumlab,选择三维可视化

image-20220421192501173

选择瓦片-》在线

image-20220421192536765

填入自己在线的3dtiles地址

image-20220421192714243

右击图层,选择定位,由于人工模型没有坐标信息,cesiumlab会把模型加载到北京天安门

image-20220421192818200

操作数据

右击开启拖拽移动,会在模型包围范围中心出现局部坐标系

image-20220421193142110

我们先确定一下模型真实的地理位置,这里可以通过百度经纬度查询系统来查询一下模型的真实位置(注意:百度的坐标系是在火星坐标系上二次加密的,因此不会太准,不过没关系我们只是参考)

image-20220421193728301

118.704031,32.164824

右击打开属性-》看到扩展(xbsjPosition),将坐标赋值进去

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnIk9cYZ-1650542433989)(http://qiliu.sunbt.ltd/qiliu_PicGo/image-20220421193827289.png)]

填完后模型会消失,不要担心,它只是去了它该去的地方了

image-20220421194006267

右击定位,我们就能看到它了,如图所示它离真实的地理位置还差一点

image-20220421194216664

这里我们就需要手动调整一下了,我们需要拖拽红、绿、蓝三个方向(红为x轴、绿为y轴、蓝为y轴)

image-20220421194305169

通过拖拽模型已经到了正确的位置了,到这我们已经成功了90%了

image-20220421194543246

获取cesium加载代码

到上面为止,如果模型尺寸和方向没为题,我们就可以获取cesium的加载代码了

cesiumlab提供了两种加载代码:一种cesium原生的加载代码,一种是earthSDK(也是他们家的,一个基于cesium源码二次开发包,很好用帮我们实现了很多功能,后面有机会也要好好介绍一下)

image-20220421195102950

点击查看cesium加载代码

image-20220421195152153

// cesium加载代码
var viewer = earth.czm.viewer;
var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
    url: '../model/tianjie/tileset.json',
    modelMatrix: Cesium.Matrix4.fromArray([0.9972459143270339,0.043718663325275964,0.05991047350079684,0,-0.03623642613173875,0.9920231602439527,-0.12073512728614089,0,-0.06471095563532905,0.11823167095432924,0.990875251585238,0,-663.0708428965881,1211.4791529159993,2974.063367189374,1]),
}));
viewer.flyTo(tileset);

其中modelMatrix(转换矩阵)已经帮我们计算好了(学习cesium就是这么简单)

我们把它放到自己的代码种就能使用了

参数介绍

image-20220421194633201

扩展种有很多参数,这里介绍一下常用的参数

xbsjPosition:包括经纬度和模型高程

xbsjRotation:这里设置模型在x、y、z轴上旋转的度数

xbsjScale:这里默认是1,表示模型不缩放,修改这三个参数,可以在x、y、z轴上缩放

最好大家都使用一下,就明白怎么做了,太方便了

这些修改好的参数都会计算在转换矩阵中,我们最后只要矩阵参数即可

image-20220421195928028

cesiumlab中还有很多功能,大家可以使用看看

  • 22
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
Cesium是一种用于创建智慧城市模型的开源平台。通过Cesium,我们可以下载智慧城市的模型数据,从而实现在虚拟环境模拟和可视化城市的不同方面。 要下载Cesium智慧城市模型,我们首先需要访问Cesium的官方网站。在该网站上,我们可以找到各种Cesium的下载选项和相关文档,以便更好地了解如何使用Cesium进行城市模拟。 下载和安装Cesium之后,我们可以开始创建智慧城市模型。首先,我们需要准备城市模型的数据。这些数据可以来自于各种渠道,如地理信息系统(GIS),传感器数据和卫星图像等。这些数据通常以三维几何模型的形式存在,如建筑物、道路、绿地等。 接下来,我们可以使用Cesium的工具和功能来加载和呈现这些城市模型数据。Cesium提供了各种功能和API,使我们能够以不同的方式展示和操作城市模型。我们可以通过调整视角、添加标记和模型、漫游和导航等方式来自定义城市模型的可视化效果。 此外,Cesium还支持与其他智慧城市数据和应用程序的集成。我们可以将Cesium模型数据与其他数据源结合使用,例如空气质量监测数据、交通流量数据和社交媒体数据等。这些集成可以帮助我们更好地理解和分析城市的不同方面,并帮助决策者做出有针对性的政策和规划。 在完成智慧城市模型的创建和配置后,我们可以将其保存和共享,以便其他人也可以访问和使用。Cesium支持模型数据的导出和共享,以便在不同的平台和环境使用。 总结而言,Cesium是一个强大的智慧城市模拟和可视化平台,可以帮助我们下载并创建智慧城市模型。使用Cesium,我们可以通过加载和处理城市模型数据来实现对城市的多方位模拟和可视化,从而更好地理解和规划城市的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙霸天

你的打赏是我不断创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值